package com.zhuchang.self_rpc.test.proxy;

import com.zhuchang.self_rpc.test.client.RpcClientHandler;
import com.zhuchang.self_rpc.test.codec.RpcRequest;
import com.zhuchang.self_rpc.test.common.RpcFuture;
import com.zhuchang.self_rpc.test.config.RpcConnectMannager;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author RenPu
 * @Date 2021/8/18 20:04
 * @Version 1.0
 * @Description:
 **/
public class RpcClientProxyImpl<T> implements InvocationHandler, RpcAsyncProxy {

    private Class<T> clzz;
    private long timeout;
    private RpcConnectMannager rpcConnectManager;

    public RpcClientProxyImpl(RpcConnectMannager rpcConnectManager, Class<T> clzz, long timeout) {
        this.clzz = clzz;
        this.timeout = timeout;
        this.rpcConnectManager = rpcConnectManager;
    }


    /**
     * invoke 代理接口调用方式（同步调用的方式）
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //1：设置封装请求对象,从代理的方法对象里获取
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setRequestId(UUID.randomUUID().toString());
        rpcRequest.setClassName(method.getDeclaringClass().getName());
        rpcRequest.setMethondName(method.getName());
        rpcRequest.setParameterTypes(method.getParameterTypes());
        rpcRequest.setParameters(args);

//        //2：选择一个client的handler去做业务处理
//        RpcClientHandler rpcClientHandler = RpcConnectMannager.getInstance().chooseHandler();
//
//
//        //3:发送真正的客户端请求，返回结果
//        //RpcFuture rpcFuture = rpcClientHandler.sendRequest(rpcRequest);  //异步发出请求

        RpcClientHandler rpcClientHandler = this.rpcConnectManager.chooseHandler();
        RpcFuture future = rpcClientHandler.sendRequest(rpcRequest);//异步发出请求

        return future.get(timeout, TimeUnit.SECONDS);
    }


    /**
     * 异步调用的方式
     *
     * @param funcName
     * @param args
     * @return
     */
    @Override
    public RpcFuture call(String funcName, Object... args) {
        //1：设置封装请求对象,从代理的方法对象里获取
        RpcRequest rpcRequest = new RpcRequest();
        rpcRequest.setRequestId(UUID.randomUUID().toString());
        rpcRequest.setClassName(this.clzz.getName());
        rpcRequest.setMethondName(funcName);

        //处理未知参数的类型
        Class[] pararmeterTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            pararmeterTypes[i] = getClassType(args[i]);
        }
        rpcRequest.setParameterTypes(pararmeterTypes);
        rpcRequest.setParameters(args);

        //2：选择一个client的handler去做业务处理
        RpcClientHandler rpcClientHandler = RpcConnectMannager.getInstance().chooseHandler();


        //3:发送真正的客户端请求，返回结果
        RpcFuture rpcFuture = rpcClientHandler.sendRequest(rpcRequest);  //异步发出请求

        return rpcFuture;
    }


    /**
     * 当方法参数类型未知时，去匹配处理相应的类型
     *
     * @param obj
     * @return
     */
    public Class<?> getClassType(Object obj) {

        Class<?> aClass = obj.getClass();
        String typeName = aClass.getName();
        if (typeName.equals("java.lang.Integer")) {
            return Integer.TYPE;
        } else if (typeName.equals("java.lang.Long")) {
            return Long.TYPE;
        } else if (typeName.equals("java.lang.Float")) {
            return Float.TYPE;
        } else if (typeName.equals("java.lang.Double")) {
            return Double.TYPE;
        } else if (typeName.equals("java.lang.Short")) {
            return Short.TYPE;
        } else if (typeName.equals("java.lang.Character")) {
            return Character.TYPE;
        } else if (typeName.equals("java.lang.Boolean")) {
            return Boolean.TYPE;
        } else if (typeName.equals("java.lang.Byte")) {
            return Byte.TYPE;
        }
        return aClass;
    }


}
